package com.anan.utils;

import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import com.anan.exception.BusinessException;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;

/**
 * @Author: Anan
 * @email: 2328791101@qq.com
 * @project_name: anan-bookkeeping
 * @time: 2023/6/2916:37
 */


public class AnanUtils {
    private static final Logger logger = LoggerFactory.getLogger(AnanUtils.class);

    private static final String ALGORITHMS = "AES/ECB/PKCS5Padding";

    @Resource
    private JavaMailSender javaMailSender;
    @Resource
    RedisUtils<Object> redisUtils;

    public static String MD5Encryption(String source,String key) {
        // 1.判断 source 是否有效
        if (source == null || source.length() == 0) {
            // 2.如果不是有效的字符串抛出异常
            throw new RuntimeException("字符串不可为空");
        }
        try {
            source = source+key;
            // 3.获取 MessageDigest 对象
            String algorithm = "md5";
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            // 4.获取明文字符串对应的字节数组
            byte[] input = source.getBytes();
            //执行加密
            byte[] output = messageDigest.digest(input);
            // 6.创建 BigInteger 对象
            int signum = 1;
            BigInteger bigInteger = new BigInteger(signum, output);
            // 7.按照 16 进制将 bigInteger 的值转换为大写字符串
            int radix = 16;
            return bigInteger.toString(radix).toUpperCase();
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    /**
     *  打乱顺序
     * @param str
     * @return
     */
    public static String DisruptSort(String str){
        char[] arr =str.toCharArray();
        Random random=new Random();
        for (int i = 0; i < arr.length; i++) {
            int a = random.nextInt(arr.length);
            char temp = arr[i];
            arr[i] = arr[a];
            arr[a] = temp;
        }
        return new String(arr);
    }

    public static void readFile(HttpServletResponse response, String fileName)  {

        response.setContentType("application/octet-stream");

        String projectPath = System.getProperty("user.dir");
        File filePath = new File(projectPath + "/file/");
        if(!filePath.exists()){
            boolean mkdirs = filePath.mkdirs();
            if (!mkdirs) {
                throw new BusinessException(400, "文件文件夹创建失败  请联系管理员创建项目file文件夹");
            }
            throw new BusinessException(400,"文件不存在");
        }
        File file = new File(projectPath + "/file/"+fileName);
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            OutputStream out = response.getOutputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            while((len = fileInputStream.read(bytes)) !=-1){
                out.write(bytes, 0, len);
            }
            out.flush();
            out.close();
            fileInputStream.close();
        } catch (IOException e) {
            throw new BusinessException(400,"文件传输失败 请重试");
        }

    }

    public static String emailSend(String toEmail,String msg,File file ){


        MailAccount account = new MailAccount();
        account.setHost("smtp.qq.com");  // 设置邮件服务器的主机名为"smtp.qq.com"。这是QQ邮箱的SMTP服务器地址。
        account.setPort(465);  // 设置邮件服务器的端口号为465。这是QQ邮箱的SMTP服务器端口号。
        account.setAuth(true);  // 设置邮件服务器需要身份验证。这意味着发送邮件时需要提供正确的用户名和密码。
        account.setFrom("2328791101@qq.com");  // 设置邮件的发件人地址为"2328791101@qq.com"。这是QQ邮箱的邮箱地址。
        account.setUser("2328791101@qq.com");  // 设置邮件的发件人用户名为"Anan记账"。这是邮件发送时显示的发件人名称。
        account.setPass("sjvtcqzfdnlrdjdh");  // 设置邮件的发件人密码为"sjvtcqzfdnlrdjdh"。这是QQ邮箱的授权码，用于身份验证。

        account.setSslEnable(true);  // 使用SSL安全连接
        //指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
        account.setSocketFactoryClass("javax.net.ssl.SSLSocketFactory");
        //如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
        account.setSocketFactoryFallback(true);
        // 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口456
        account.setSocketFactoryPort(465);

        String title = "用户注册验证码";
        String html = String.format("<h1>【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。</h1>", msg);;

        if(file==null) {
            return MailUtil.send(account, toEmail, title, html, false);
        }else{
            return MailUtil.send(account, toEmail, title, html, true, file);
        }

    }

    public boolean sendCheckCode(String email) {
        try {
            String code = RandomStringUtils.random(5,false,true);
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //邮件发件人
            helper.setFrom("2328791101@qq.com");
            //邮件收件人 1或多个
            helper.setTo(email);
            //邮件主题
            helper.setSubject("用户注册验证码");
            //邮件内容
            helper.setText(String.format("【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。", code));
            //邮件发送时间
            helper.setSentDate(new Date());
            // 发送邮件
            javaMailSender.send(message);
            logger.info("用户 "+email + " 的验证码 "+ code +" 发送成功！");
            redisUtils.put(email, code, 5 * 60L);
            return true;
        } catch (Exception e) {
            logger.error("邮件发送失败! error:", e);
            throw new BusinessException("邮件发送失败");
        }
    }
    public static boolean stringIsEmpty(Object s) {
        if(s == null){
            return true;
        }
        String str = s.toString();
        if (null == str || "".equals(str) || "null".equals(str) || "\u0000".equals(str)) {
            return true;
        } else if ("".equals(str.trim())) {
            return true;
        }
        return false;
    }

    /**
     * 加密
     *
     * @param content 内容
     * @param key     key
     * @return java.lang.String
     */
    public static String encrypt(String content, String key) {
        try {
            //获得密码的字节数组
            byte[] raw = key.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            //获取加密内容的字节数组(设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            //密码器加密数据
            byte[] encodeContent = cipher.doFinal(byteContent);
            //将加密后的数据转换为字符串返回

            return Base64.getEncoder().encodeToString(encodeContent);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密
     *
     * @param encryptStr 加密后的内容
     * @param decryptKey 解密key
     * @return java.lang.String
     */
    public static String decrypt(String encryptStr, String decryptKey) {
        try {
            //获得密码的字节数组
            byte[] raw = decryptKey.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥
            cipher.init(Cipher.DECRYPT_MODE, skey);
            //把密文字符串转回密文字节数组
            byte[] encodeContent = Base64.getDecoder().decode(encryptStr);
            //密码器解密数据
            byte[] byteContent = cipher.doFinal(encodeContent);
            //将解密后的数据转换为字符串返回
            return new String(byteContent, StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("String : {} aes decrypt error", encryptStr);
            return null;
        }
    }

    public static void main(String[] args) {
//        System.out.println(MD5Encryption("root", "root"));
//        System.out.println(DisruptSort(String.valueOf(System.currentTimeMillis())));
        System.out.println(encrypt("anan", "46053F08D4A8411C825CDF61885265E7"));
        System.out.println(decrypt("MvkGW9eGU/tK1Q+PAyeXIg==", "46053F08D4A8411C825CDF61885265E7"));

    }
}
